#include "emitter.h"
#include "utils.h"
#include "coord.h"
#include "csbmath.h"

#ifdef __cplusplus
extern "C" {
#endif
/*********************| 内部数据定义 |*********************/
/* 发射器事件控制变量名 */
#define EM_CON_T_NowFme	0	//当前帧
#define EM_CON_T_X	1	//X坐标
#define EM_CON_T_Y	2	//Y坐标
#define EM_CON_T_r	3	//半径
#define EM_CON_T_RV	4	//半径方向
#define EM_CON_T_Muzzle	5	//条数
#define EM_CON_T_Freq	6	//周期
#define EM_CON_T_Angle	7	//角度
#define EM_CON_T_Range	8	//范围
#define EM_CON_T_WS	9	//宽比
#define EM_CON_T_HS	10	//高比
#define EM_CON_T_Alpha	11	//不透明度
#define EM_CON_T_Opdir	12	//朝向
/* 发射器事件结果 */ 
// 特殊事件
#define EM_RES_T_BORN	-2	//恢复到初始状态
#define EM_RES_T_MEMIT	-3	//额外发射
// 常规事件
#define EM_RES_T_X	0	//X坐标
#define EM_RES_T_Y	1	//Y坐标
#define EM_RES_T_r	2	//半径
#define EM_RES_T_rV	3	//半径方向
#define EM_RES_T_Muzzle	4	//条数
#define EM_RES_T_Freq	5	//周期
#define EM_RES_T_Angle	6	//角度
#define EM_RES_T_Range	7	//范围
#define EM_RES_T_v	8	//速度
#define EM_RES_T_vV	9	//速度方向
#define EM_RES_T_va	10	//加速度
#define EM_RES_T_vaV	11	//加速度方向
/* 从这里开始才是子弹有的 */
#define EM_OBJ_BULLET_ACTION_BOUNDARY	12
#define EM_RES_BT_life	12	//生命
#define EM_RES_BT_ID	13	//类型
#define EM_RES_BT_WS	14	//宽比
#define EM_RES_BT_HS	15	//高比
#define EM_RES_BT_R	16	//R
#define EM_RES_BT_G	17	//G
#define EM_RES_BT_B	18	//B
#define EM_RES_BT_Alpha	19	//不透明度
#define EM_RES_BT_Opdir	20	//朝向
#define EM_RES_BT_v	21	//子弹速度
#define EM_RES_BT_vV	22	//子弹速度方向
#define EM_RES_BT_va	23	//子弹加速度
#define EM_RES_BT_vaV	24	//子弹加速度方向
#define EM_RES_BT_VHS	25	//横比
#define EM_RES_BT_VWS	26	//纵比
#define EM_RES_ET_Atom	27	//雾化效果
#define EM_RES_ET_Fade	28	//消除效果
#define EM_RES_ET_Light	29	//高光效果
#define EM_RES_ET_Smear	30	//拖影效果
#define EM_RES_ET_OutSc	31	//出屏即消
#define EM_RES_ET_Invin	32	//无敌状态

CS_BUF_DECLAR(EMITTER_BULLET_BUF_SIZE, emitterbu_t)
CS_BUF_DECLAR(EMITTER_BUF_SIZE, emitter_t)
/*********************| static data |*********************/
/* 发射器的子弹 */
typedef struct {
	bulletdata_t	b;		//子弹
	color_t		color;		//颜色和alpha
	scale_t		vRate;		//速度缩放倍率
	int32_t		effect;		//特效
	ac_t		aclist;		//子弹事件
} emitterbudata_t;

/* 发射器 */
typedef struct{
	csobjdata_t	objtag;		//元素标签
	pos_t		emitpos;	//发射坐标
	pos_t		emitPosVar; 	//坐标随机量
	ac_t		aclist;		//事件
	emitterbudata_t	bullet;		//子弹
} emitterdata_t;

/*********************| static func |*********************/

static bool em_action_match(const int8_t t, const int8_t s, const int d,
			    const csnode_t* pcs)
{
	emitter_t* pem = (emitter_t*)pcs->pobj;
	switch (t) {
	case EM_CON_T_NowFme :
		return action_con_match(pem->obj.life, s, d);
	case EM_CON_T_X :
		return action_con_match(pem->obj.ele.pos.x, s, d);
	case EM_CON_T_Y :
		return action_con_match(pem->obj.ele.pos.y, s, d);
	case EM_CON_T_r :
		return action_con_match(pem->obj.emitedge.r, s, d);
	case EM_CON_T_RV :
		return action_con_match(pem->obj.emitedge.angle, s, d);
	case EM_CON_T_Muzzle :
		return action_con_match(pem->obj.nmuzzle, s, d);
	case EM_CON_T_Freq :
		return action_con_match(pem->obj.freq, s, d);
	case EM_CON_T_Angle :
		return action_con_match(pem->obj.rotateOffset, s, d);
	case EM_CON_T_Range :
		return action_con_match(pem->obj.emitRange, s, d);
	case EM_CON_T_WS :
		return action_con_match(pem->buScale.xs, s, d);
	case EM_CON_T_HS :
		return action_con_match(pem->buScale.ys, s, d);
	case EM_CON_T_Alpha :
		return action_con_match(pem->bucolor.A, s, d);
//	case EM_CON_T_Opdir :
//	NOTE:朝向暂时被顾略
	default:
		return false;
	}
}

#define CTL_LESS0_E0(_d_, _tmp_, _eff_) \
	_tmp_ = action_res2(_d_, _eff_->ressign,_eff_->data);\
	if (_tmp_ < 0) _d_ = 0;\
	else _d_ = tmp;\
	return

#define CTL_EFFECT_BY_RES_DATA(effect, mask, eff) \
	if (!eff->n) {\
		if (eff->data) { effect = CSB_FLAG_ON(effect, mask); }\
		else { effect = CSB_FLAG_OFF(effect, mask); }\
	}\
	return

#define CTL_COLOR_RES_DATA(_d_, _tmp_, _eff_) \
	_tmp_ = action_res2(_d_, _eff_->ressign, _eff_->data);\
	if (_tmp_ < 0) { _d_ = 0;} \
	else if (_tmp_ > 255) { _d_ = 255;}\
	else { _d_= _tmp_;}\
	return


static void emitter_2origin(const emitterdata_t * pdata, emitter_t* pem, bool freeaction)
{
	CSB_NO_VRET(pdata && pem);
	pem->obj.ele.flag = 0;
	pem->obj.ele.pos = pdata->emitpos;
	if (AUTO_SELF == pdata->emitpos.x) {
		pem->obj.ele.flag |= X_AM;
	}
	if (AUTO_SELF == pdata->emitpos.y) {
		pem->obj.ele.flag |= Y_AM;
	}
	if (AUTO_SELF == pdata->objtag.angle) {
		pem->obj.ele.flag |= R_AM;
		pem->obj.rotateOffset = 0;
	} else {
		pem->obj.rotateOffset = pdata->objtag.angle;
	}
	pem->obj.ele.rotate = pdata->objtag.angle;
	pem->obj.ele.scale.xs =pem->obj.ele.scale.ys = 1.0f;
	pem->buScale = pdata->bullet.b.scale;

	pem->obj.emitRange = pdata->objtag.emitrange;
	pem->obj.freq = pdata->objtag.freq;
	pem->obj.nmuzzle = pdata->objtag.nmuzzle;
	pem->obj.emitedge = pdata->objtag.emitedge;
	pem->obj.v = pdata->objtag.v;
	pem->obj.va = pdata->objtag.va;

	pem->buattr.ID = pdata->bullet.b.ID;
	pem->buattr.v.v = pdata->bullet.b.v;
	pem->buattr.v.dir = pem->obj.ele.rotate;
	pem->buattr.lifetime = pdata->bullet.b.life;
	pem->buattr.life = 0;
	pem->buattr.va = pdata->bullet.b.va;
	if (AUTO_SELF == pem->buattr.va.dir) {
		pem->obj.ele.flag |= RB_AM;
	}
	pem->buattr.vRate = pdata->bullet.vRate;
	pem->bucolor = pdata->bullet.color;
	pem->bueffect = pdata->bullet.effect;
	if (freeaction) {
		ac_free(pem->aclist);
	}
	pem->aclist = ac_buf_copy(pdata->aclist);
}

#define RES_TO_ME_DRATIO(_eff_, _d_)  \
	_eff_->data = (_eff_->data - _d_) / _eff_->n;\
	return true
// 处理发射器自身的事件
static bool	emitter_ac_for(action_t* pac, void* flag)
{
	csnode_t* pcs = (csnode_t*)flag;
	// 判定条件是否触发
	bool b1 = em_action_match(CON_GET_TYPE1(pac->con.tAs), CON_GET_SIGN1(pac->con.tAs), pac->con.data0, pcs);
	bool b2 = true;
	const int8_t aor = CON_GET_AOR(pac->con.tAs);
	if (CON_SIGN_TRUE != aor) {
		b2 =em_action_match(CON_GET_TYPE2(pac->con.tAs), CON_GET_SIGN2(pac->con.tAs), pac->con.data1, pcs);
	}
	if (!action_2con_match(b1, b2, aor))
		return false;
	emitter_t* pem = (emitter_t*)pcs->pobj;
	action_eff_t* eff = action_make_action_eff(pac);
	CSB_NO_RET(eff, true);
	list_insert(&pcs->pobj->ac_eff_list, (void*)eff, 0, 0);
	// 如果是正比且变化符号是变化到，那么就需要转换成增量处理
	CSB_NO_RET(CON_RES_TO == eff->ressign && CON_ME_DRATIO == eff->mesign, true);
	eff->ressign = CON_RES_ADD;
	switch (eff->type) {
	case EM_RES_T_BORN :
	case EM_RES_T_MEMIT :
	case EM_RES_ET_Atom:
	case EM_RES_ET_Fade:
	case EM_RES_ET_Light:
	case EM_RES_ET_Smear:
	case EM_RES_ET_OutSc:
	case EM_RES_ET_Invin:
		return true;
	// 常规事件
	case EM_RES_T_X	:
		RES_TO_ME_DRATIO(eff, pem->obj.ele.pos.x);
	case EM_RES_T_Y	:
		RES_TO_ME_DRATIO(eff, pem->obj.ele.pos.y);
	case EM_RES_T_r	:
		RES_TO_ME_DRATIO(eff, pem->obj.emitedge.r);
	case EM_RES_T_rV :
		RES_TO_ME_DRATIO(eff, pem->obj.emitedge.angle);
	case EM_RES_T_Muzzle :
		RES_TO_ME_DRATIO(eff, pem->obj.nmuzzle);
	case EM_RES_T_Freq :
		RES_TO_ME_DRATIO(eff, pem->obj.freq);
	case EM_RES_T_Angle :
		RES_TO_ME_DRATIO(eff, pem->obj.rotateOffset);
	case EM_RES_T_Range :
		RES_TO_ME_DRATIO(eff, pem->obj.emitRange);
	case EM_RES_T_v	:
		RES_TO_ME_DRATIO(eff, pem->obj.v.v);
	case EM_RES_T_vV :
		RES_TO_ME_DRATIO(eff, pem->obj.v.dir);
	case EM_RES_T_va :
		RES_TO_ME_DRATIO(eff, pem->obj.va.v);
	case EM_RES_T_vaV :
		RES_TO_ME_DRATIO(eff, pem->obj.va.dir);
	case EM_RES_BT_life:
		RES_TO_ME_DRATIO(eff, pem->buattr.lifetime);
	case EM_RES_BT_ID:
		RES_TO_ME_DRATIO(eff, pem->buattr.ID);
	case EM_RES_BT_WS:
		RES_TO_ME_DRATIO(eff, pem->buScale.xs);
	case EM_RES_BT_HS:
		RES_TO_ME_DRATIO(eff, pem->buScale.ys);
	case EM_RES_BT_R:
		RES_TO_ME_DRATIO(eff, pem->bucolor.R);
	case EM_RES_BT_G:
		RES_TO_ME_DRATIO(eff, pem->bucolor.G);
	case EM_RES_BT_B:
		RES_TO_ME_DRATIO(eff, pem->bucolor.B);
	case EM_RES_BT_Alpha:
		RES_TO_ME_DRATIO(eff, pem->bucolor.A);
//	case EM_RES_T_Opdir:NOTE:朝向暂时不支持
	case EM_RES_BT_v:
		RES_TO_ME_DRATIO(eff, pem->buattr.v.v);
	case EM_RES_BT_vV:
		RES_TO_ME_DRATIO(eff, pem->buattr.v.dir);
	case EM_RES_BT_va:
		RES_TO_ME_DRATIO(eff, pem->buattr.va.v);
	case EM_RES_BT_vaV:
		RES_TO_ME_DRATIO(eff, pem->buattr.va.dir);
	case EM_RES_BT_VHS:
		RES_TO_ME_DRATIO(eff, pem->buattr.vRate.ys);
	case EM_RES_BT_VWS:
		RES_TO_ME_DRATIO(eff, pem->buattr.vRate.xs);
	}

	return true;
}

static void emitter_aceff_for(const action_eff_t* eff, void* flag)
{
	csnode_t* pcs = (csnode_t*)flag;
	emitter_t* pem = (emitter_t*)pcs->pobj;
	// TODO
	ssize_t tmp = 0;
	switch (eff->type) {
	case EM_RES_T_BORN :
		if (!eff->n)
			emitter_2origin((emitterdata_t*)pcs->pobjdata, (emitter_t*)pcs->pobj, true);
		return;
	case EM_RES_T_MEMIT :
		if (!eff->n)
			emitter_emit(pcs);
		return;
	// 常规事件
	case EM_RES_T_X	:
		pem->obj.ele.pos.x = action_res2(pem->obj.ele.pos.x, eff->ressign, eff->data);
		pem->obj.ele.flag = CSB_FLAG_TO(AUTO_SELF == pem->obj.ele.pos.x, pem->obj.ele.flag, X_AM);
		return;
	case EM_RES_T_Y	:
		pem->obj.ele.pos.y = action_res2(pem->obj.ele.pos.y, eff->ressign, eff->data);
		pem->obj.ele.flag = CSB_FLAG_TO(AUTO_SELF == pem->obj.ele.pos.y, pem->obj.ele.flag, Y_AM);
		return;
	case EM_RES_T_r	:
		CTL_LESS0_E0(pem->obj.emitedge.r, tmp, eff);
	case EM_RES_T_rV :
		pem->obj.emitedge.angle = action_res2(pem->obj.emitedge.angle, eff->ressign, eff->data);
		return;
	case EM_RES_T_Muzzle :
		CTL_LESS0_E0(pem->obj.nmuzzle, tmp, eff);
	case EM_RES_T_Freq :
		CTL_LESS0_E0(pem->obj.freq, tmp, eff);
	case EM_RES_T_Angle :
		if (AUTO_SELF == eff->data) {
			pem->obj.rotateOffset = AUTO_SELF;
			pem->obj.ele.flag |=  R_AM;
		} else {
			pem->obj.rotateOffset = action_res2(pem->obj.rotateOffset, eff->ressign, eff->data);
		}
		pem->buattr.v.dir = pem->obj.rotateOffset;
		return;
	case EM_RES_T_Range :
		pem->obj.emitRange = action_res2(pem->obj.emitRange, eff->ressign, eff->data);
		return;
	case EM_RES_T_v	:
		pem->obj.v.v = action_res2(pem->obj.v.v, eff->ressign, eff->data);
		return;
	case EM_RES_T_vV :
		pem->obj.v.dir = action_res2(pem->obj.v.dir, eff->ressign, eff->data);
		return;
	case EM_RES_T_va :
		pem->obj.va.v = action_res2(pem->obj.va.v, eff->ressign, eff->data);
		return;
	case EM_RES_T_vaV :
		pem->obj.va.dir = action_res2(pem->obj.va.dir, eff->ressign, eff->data);
		return;

	case EM_RES_BT_life:
		CTL_LESS0_E0(pem->buattr.lifetime, tmp, eff);
	case EM_RES_BT_ID:
		pem->buattr.ID = action_res2(pem->buattr.ID, eff->ressign, eff->data);
		return;
	case EM_RES_BT_WS:
		CTL_LESS0_E0(pem->buScale.xs, tmp, eff);
	case EM_RES_BT_HS:
		CTL_LESS0_E0(pem->buScale.ys, tmp, eff);

	case EM_RES_BT_R:
		CTL_COLOR_RES_DATA(pem->bucolor.R, tmp, eff);
	case EM_RES_BT_G:
		CTL_COLOR_RES_DATA(pem->bucolor.G, tmp, eff);
	case EM_RES_BT_B:
		CTL_COLOR_RES_DATA(pem->bucolor.B, tmp, eff);
	case EM_RES_BT_Alpha:
		CTL_COLOR_RES_DATA(pem->bucolor.A, tmp, eff);
//	case EM_RES_T_Opdir:NOTE:朝向暂时不支持
	case EM_RES_BT_v:
		pem->buattr.v.v = action_res2(pem->buattr.v.v, eff->ressign, eff->data);
		return;
	case EM_RES_BT_vV:
		pem->buattr.v.dir = action_res2(pem->buattr.v.dir, eff->ressign, eff->data);
		return;
	case EM_RES_BT_va:
		pem->buattr.va.v = action_res2(pem->buattr.va.v, eff->ressign, eff->data);
		return;
	case EM_RES_BT_vaV:
		if (AUTO_SELF == eff->data) {
			pem->buattr.va.dir = AUTO_SELF;
			pem->obj.ele.flag |= RB_AM;
		} else {
			pem->buattr.va.dir = action_res2(pem->buattr.va.dir, eff->ressign, eff->data);
		}
		return;
	case EM_RES_BT_VHS:
		pem->buattr.vRate.ys = action_res2(pem->buattr.vRate.ys, eff->ressign, eff->data);
		return;
	case EM_RES_BT_VWS:
		pem->buattr.vRate.xs = action_res2(pem->buattr.vRate.xs, eff->ressign, eff->data);
		return;

	// 对于特效变化到0，就是关闭，否则就是开启
	case EM_RES_ET_Atom:
		CTL_EFFECT_BY_RES_DATA(pem->bueffect, BU_EFF_Atom, eff);
	case EM_RES_ET_Fade:
		CTL_EFFECT_BY_RES_DATA(pem->bueffect, BU_EFF_Fade, eff);
	case EM_RES_ET_Light:
		CTL_EFFECT_BY_RES_DATA(pem->bueffect, BU_EFF_Light, eff);
	case EM_RES_ET_Smear:
		CTL_EFFECT_BY_RES_DATA(pem->bueffect, BU_EFF_Smear, eff);
	case EM_RES_ET_OutSc:
		CTL_EFFECT_BY_RES_DATA(pem->bueffect, BU_EFF_OutSc, eff);
	case EM_RES_ET_Invin:
		CTL_EFFECT_BY_RES_DATA(pem->bueffect, BU_EFF_Invin, eff);
	}
}

static bool	embu_action_match(const int8_t t, const int8_t s, const int d,
				     const emitterbu_t* pbu)
{
	switch (t) {
	case EM_CON_T_NowFme :
		return action_con_match(pbu->b.attr.life, s, d);
	case EM_CON_T_X :
		return action_con_match(pbu->b.ele.pos.x, s, d);
	case EM_CON_T_Y :
		return action_con_match(pbu->b.ele.pos.y, s, d);
	default:
		return false;
	}
}

/* 处理发射器子弹的事件 */
static bool	emitter_buac_for(action_t* pac, void* flag)
{
	emitterbu_t* pbu = (emitterbu_t*)flag;
	// 判定条件是否触发
	bool b1 = embu_action_match(CON_GET_TYPE1(pac->con.tAs), CON_GET_SIGN1(pac->con.tAs), pac->con.data0, pbu);
	bool b2 = true;
	const int8_t aor = CON_GET_AOR(pac->con.tAs);
	if (CON_SIGN_TRUE != aor) {
		b2 =embu_action_match(CON_GET_TYPE2(pac->con.tAs), CON_GET_SIGN2(pac->con.tAs), pac->con.data1, pbu);
	}
	if (!action_2con_match(b1, b2, aor))
		return false;
	// 条件满足，进行处理
	action_eff_t* eff = action_make_action_eff(pac);
	CSB_NO_RET(eff, true);
	list_insert(&pbu->b.ac_eff_list, (void*)eff, 0, 0);
	// 如果是正比且变化符号是变化到，那么就需要转换成增量处理
	CSB_NO_RET(CON_RES_TO == eff->ressign && CON_ME_DRATIO == eff->mesign, true);
	eff->ressign = CON_RES_ADD;
	switch (pac->restype) {
	case EM_RES_BT_life:
		RES_TO_ME_DRATIO(eff, pbu->b.attr.lifetime);
	case EM_RES_BT_ID:
		RES_TO_ME_DRATIO(eff, pbu->b.attr.ID);
	case EM_RES_BT_WS:
		RES_TO_ME_DRATIO(eff, pbu->b.ele.scale.xs);
	case EM_RES_BT_HS:
		RES_TO_ME_DRATIO(eff, pbu->b.ele.scale.ys);
	case EM_RES_BT_R:
		RES_TO_ME_DRATIO(eff, pbu->color.R);
	case EM_RES_BT_G:
		RES_TO_ME_DRATIO(eff, pbu->color.G);
	case EM_RES_BT_B:
		RES_TO_ME_DRATIO(eff, pbu->color.B);
	case EM_RES_BT_Alpha:
		RES_TO_ME_DRATIO(eff, pbu->color.A);
//	case EM_RES_T_Opdir:
//	NOTE:朝向暂时不控制
	case EM_RES_BT_v:
		RES_TO_ME_DRATIO(eff, pbu->b.attr.v.v);
	case EM_RES_BT_vV:
		RES_TO_ME_DRATIO(eff, pbu->b.attr.v.dir);
	case EM_RES_BT_va:
		RES_TO_ME_DRATIO(eff, pbu->b.attr.va.v);
	case EM_RES_BT_vaV:
		RES_TO_ME_DRATIO(eff, pbu->b.attr.va.dir);
	case EM_RES_BT_VHS:
		RES_TO_ME_DRATIO(eff, pbu->b.attr.vRate.ys);
	case EM_RES_BT_VWS:
		RES_TO_ME_DRATIO(eff, pbu->b.attr.vRate.xs);
	case EM_RES_ET_Atom:
	case EM_RES_ET_Fade:
	case EM_RES_ET_Light:
	case EM_RES_ET_Smear:
	case EM_RES_ET_OutSc:
	case EM_RES_ET_Invin:
		return true;
	}
	return true;
}
static void emitterbu_aceff_for(const action_eff_t* eff, void* flag)
{
	emitterbu_t* pbu = (emitterbu_t*)flag;
	ssize_t tmp = 0;
	switch (eff->type) {
	case EM_RES_BT_life:
		CTL_LESS0_E0(pbu->b.attr.lifetime, tmp, eff);
	case EM_RES_BT_ID:
		pbu->b.attr.ID = action_res2(pbu->b.attr.ID, eff->ressign, eff->data);
		return;
	case EM_RES_BT_WS:
		CTL_LESS0_E0(pbu->b.ele.scale.xs, tmp, eff);
	case EM_RES_BT_HS:
		CTL_LESS0_E0(pbu->b.ele.scale.ys, tmp, eff);
	case EM_RES_BT_R:
		CTL_COLOR_RES_DATA(pbu->color.R, tmp, eff);
	case EM_RES_BT_G:
		CTL_COLOR_RES_DATA(pbu->color.G, tmp, eff);
	case EM_RES_BT_B:
		CTL_COLOR_RES_DATA(pbu->color.B, tmp, eff);
	case EM_RES_BT_Alpha:
		CTL_COLOR_RES_DATA(pbu->color.A, tmp, eff);
//	case EM_RES_T_Opdir:
//	NOTE:朝向暂时不控制
	case EM_RES_BT_v:
		pbu->b.attr.v.v = action_res2(pbu->b.attr.v.v, eff->ressign, eff->data);
		return;
	case EM_RES_BT_vV:
		pbu->b.attr.v.dir = action_res2(pbu->b.attr.v.dir, eff->ressign, eff->data);
		pbu->b.ele.rotate = pbu->b.attr.v.dir;
		return;
	case EM_RES_BT_va:
		pbu->b.attr.va.v = action_res2(pbu->b.attr.va.v, eff->ressign, eff->data);
		return;
	case EM_RES_BT_vaV:
		if (AUTO_SELF == eff->data) {
			pbu->b.attr.va.dir = AUTO_SELF;
			pbu->b.ele.flag |= RBRT_AM;
		} else {
			pbu->b.attr.va.dir = action_res2(pbu->b.attr.va.dir, eff->ressign, eff->data);
		}
		return;
	case EM_RES_BT_VHS:
		pbu->b.attr.vRate.ys = action_res2(pbu->b.attr.vRate.ys, eff->ressign, eff->data);
		return;
	case EM_RES_BT_VWS:
		pbu->b.attr.vRate.xs = action_res2(pbu->b.attr.vRate.ys, eff->ressign, eff->data);
		return;
	// 对于特效变化到0，就是关闭，否则就是开启
	case EM_RES_ET_Atom:
		CTL_EFFECT_BY_RES_DATA(pbu->effect, BU_EFF_Atom, eff);
	case EM_RES_ET_Fade:
		CTL_EFFECT_BY_RES_DATA(pbu->effect, BU_EFF_Fade, eff);
	case EM_RES_ET_Light:
		CTL_EFFECT_BY_RES_DATA(pbu->effect, BU_EFF_Light, eff);
	case EM_RES_ET_Smear:
		CTL_EFFECT_BY_RES_DATA(pbu->effect, BU_EFF_Smear, eff);
	case EM_RES_ET_OutSc:
		CTL_EFFECT_BY_RES_DATA(pbu->effect, BU_EFF_OutSc, eff);
	case EM_RES_ET_Invin:
		CTL_EFFECT_BY_RES_DATA(pbu->effect, BU_EFF_Invin, eff);
	}
}

struct xyvlsm_t {
	int	userotate;
	float	rotate;
	v_t	v;
	v_t	va;
	scale_t	vRate;
};

/* 计算xy坐标系上的坐标增量 */
static void	xy_vlsm(struct xyvlsm_t* p, pos_t* out)
{
	float tmpvd = CSB_DEG2RAD(-p->v.dir);
	float tmpvad = CSB_DEG2RAD(-p->va.dir);
	float tmpv = p->v.v;
	if (1.0f != p->vRate.xs || 1.0f != p->vRate.ys) {
		const float radian = p->userotate ? CSB_DEG2RAD(-p->rotate) : tmpvd;
		tmpv = CSB_sqrt(CSB_pow(tmpv * CSB_sin(radian) * p->vRate.ys, 2)
		             + CSB_pow(tmpv * CSB_cos(radian) * p->vRate.xs, 2));
	}
	out->x = tmpv * CSB_cos(tmpvd) + p->va.v * CSB_cos(tmpvad) * 0.5f;
	out->y = tmpv * CSB_sin(tmpvd) + p->va.v * CSB_sin(tmpvad) * 0.5f;

	// 计算加速度对速度影响的合速度结果
	CSB_YES_VRET(0.0f == p->va.v);
	float anoffset = p->v.dir - p->va.dir;
	tmpvd = CSB_fabs(CSB_angle_normalize_180(anoffset));
	if (tmpvd < 0.01f) {
		// 加速度和速度方向相同
		p->v.v += p->va.v;
		if (p->v.v < 0) {
			p->v.v = -p->v.v;
			p->v.dir += 180.0f;
		}
		return;
	}
	if ((180.0f - tmpvd) < 0.1f) {
		// 加速度方向和速度方向相反
		p->v.v -= p->va.v;
		if (p->v.v < 0) {
			p->v.v = -p->v.v;
			p->v.dir += 180.0f;
		}
		return;
	}
	
	// 加速度方向和速度方向有夹角
	tmpv = p->v.v;
	float aa = tmpv * tmpv;
	float bb = p->va.v * p->va.v;

	float tmpangle = tmpvd - 90.0f;
	// 计算速度方向所在边对的角tmpvad
	if (ERROR_IS_TRUE(tmpangle, 0.01f)) {
		tmpvad = CSB_atan(p->va.v / tmpv);
		p->v.v = CSB_sqrt(aa + bb);
	} else {
		// 如果是锐角，那么应做加法，如果是钝角，那么应做减法
		tmpvd = tmpv * p->va.v * CSB_cos(CSB_DEG2RAD(tmpvd));
		p->v.v = CSB_sqrt(aa + bb + tmpvd + tmpvd);
		tmpvad = CSB_acos((aa + tmpvd) / (tmpv * p->v.v) - 0.0000013f);
	}
	// 得到了一个正锐角的加速度方向和新的速度方向的夹角，需要确定是加还是减
	tmpvd = CSB_RAD2DEG(tmpvad);
	if (CSB_angle_normalize_180(anoffset) < 0) {
		p->v.dir += tmpvd;
	} else {
		p->v.dir -= tmpvd;
	}
}

static int	emitter_bu_update(void** datare, void* ctldata)
{
	emitterbu_t* pe = (emitterbu_t*)(*datare);
	csnode_t* pcs = (csnode_t*)ctldata;
	// 判定生命是否结束
	++pe->b.attr.life;
	if (pe->b.attr.life >= pe->b.attr.lifetime) {
		if (pcs->cbs.on_budead) {
			pcs->cbs.on_budead((bullet_t*)pe, pcs->cbs.udata);
		}
		emitterbu_buf_return(pe);
		return BULLET_UPDATE_DEAD;
	}
	ac_foreach(pe->aclist, emitter_buac_for, pe->b.attr.life, (void*)pe);
	action_eff_list_for(&pe->b.ac_eff_list, emitterbu_aceff_for, (void*)pe);
	// 加速度方向的自机
	if (CSB_FLAG_TEST(pe->b.ele.flag, RBRT_AM) && pcs->cbs.on_am) {
		pe->b.attr.va.dir = CSB_rotate_p2p(&pe->b.ele.pos, &pcs->cbs.autoPos);
	}
	// 调整子弹坐标
	pos_t offset;
	struct xyvlsm_t vlsmt = { 0, 0, pe->b.attr.v, pe->b.attr.va, pe->b.attr.vRate};
	xy_vlsm(&vlsmt,  &offset);
	pe->b.attr.v = vlsmt.v;
	pe->b.ele.rotate = vlsmt.v.dir;
	pe->b.ele.pos.x += offset.x;
	pe->b.ele.pos.y -= offset.y;
	// 判定出屏即消
	if (CSB_FLAG_TEST(pe->effect, BU_EFF_OutSc) && !IN_COORD_WORLD(pe->b.ele.pos)) {
		if (pcs->cbs.on_budead) {
			pcs->cbs.on_budead((bullet_t*)pe, pcs->cbs.udata);
		}
		emitterbu_buf_return(pe);
		return BULLET_UPDATE_DEAD;
	}
	if (pcs->cbs.on_buupdate) {
		int ret = pcs->cbs.on_buupdate((bullet_t*)pe, pcs->cbs.udata);
		if ( BULLET_UPDATE_DEAD == ret) {
			if (pcs->cbs.on_budead) {
				pcs->cbs.on_budead((bullet_t*)pe, pcs->cbs.udata);
			}
			emitterbu_buf_return(pe);
		}
		return ret;
	}
	return BULLET_UPDATE_CONTINUE;
}

/*********************| extern functions |*********************/
CSB_DLL csobjdata_t* emitterdata_read(unsigned char* data, const uint32_t totalframe)
{
	ZERO_MALLOC(pem, emitterdata_t);
	// read csobj_t data len
	pem->objtag.totalframe = totalframe;
	uint32_t offset = sizeof(csobjdata_t) - sizeof(totalframe);
	memcpy((unsigned char*)(&pem->objtag) + sizeof(totalframe), data, offset);
	if (pem->objtag.fe > pem->objtag.totalframe) {
		pem->objtag.fe = pem->objtag.totalframe;
	}
	// read emitpos
	memcpy(&pem->emitpos, data + offset, sizeof(pem->emitpos));
	offset += sizeof(pem->emitpos);
	memcpy(&pem->emitPosVar, data + offset, sizeof(pem->emitPosVar));
	offset += sizeof(pem->emitPosVar);
	// read action
	offset += actiondata_read(&pem->aclist, data + offset, 0);
	// read bullet
	memcpy(&pem->bullet, data + offset, sizeof(emitterbudata_t) - sizeof(ac_t));
	offset += sizeof(emitterbudata_t) - sizeof(ac_t);
	actiondata_read(&pem->bullet.aclist, data + offset, EM_OBJ_BULLET_ACTION_BOUNDARY);
	return (csobjdata_t*)pem;
}


CSB_DLL emitter_t* emitterdata_make_obj(const csobjdata_t* pdata)
{
	const emitterdata_t* pem = (const emitterdata_t*)pdata;
	emitter_t* ret = emitter_buf_rent();
	emitter_2origin(pem, ret, false);
	ret->obj.life = 0;
	return ret;
}


CSB_DLL void emitterdata_free(csobjdata_t* pemitter)
{
	emitterdata_t* pem = (emitterdata_t*)pemitter;
	CSB_LOG("%s emitter was released\n", pem->objtag.name);
	ac_free(pem->aclist);
	ac_free(pem->bullet.aclist);
	free(pem);
}

CSB_DLL void emitter_buf_init()
{
	CS_BUF_INIT(emitterbu_t);
	CS_BUF_INIT(emitter_t);
}

CSB_DLL void emitter_buf_end(bool force)
{
	CS_BUF_END(emitter_t, force);
	CS_BUF_END(emitterbu_t, force);
}

CSB_DLL emitter_t* emitter_buf_rent()
{
	CS_BUF_RENT(emitter_t, ret);
	return ret;
}

CSB_DLL void emitter_buf_return(emitter_t* pem)
{
	CS_BUF_RETURN(emitter_t, pem);
	ac_free(pem->aclist);
	action_eff_list_clean(&pem->obj.ac_eff_list);
}

CSB_DLL void emitter_emit(csnode_t* pcsn)
{
	emitterdata_t* src = (emitterdata_t*)pcsn->pobjdata;
	emitter_t* pem = (emitter_t*)pcsn->pobj;
	// 确定发射多少枚子弹
	const int32_t nmuzzle = pem->obj.nmuzzle + RAND_VAR_INT(src->objtag.nmuzzleVar);
	if (nmuzzle <= 0) return;
	// 三个用于发射角度计算的常量
	const float C = (float)(pem->obj.emitRange + RAND_VAR_INT(src->objtag.emitrangeVar)) / nmuzzle;
	const float halfC = (nmuzzle % 2) ? 0 : (C / 2);
	const float sangle = RAND_VAR(src->objtag.angleVar);
	const float amend = ((nmuzzle - 1) / 2) * C;
	// 随机速度
	const float tv = pem->buattr.v.v + RAND_VAR(src->bullet.b.vVar);
	if (CSB_FLAG_TEST(pem->obj.ele.flag, RB_AM) && pcsn->cbs.on_am) {
		pem->buattr.va.dir = CSB_rotate_p2p(&pem->obj.ele.pos, &pcsn->cbs.autoPos);
	}
	const v_t va = { pem->buattr.va.v + RAND_VAR(src->bullet.b.vaVar.v),
			 pem->buattr.va.dir + RAND_VAR(src->bullet.b.vaVar.dir)};

	//发射范围, 和弧度确定, 随机半径
	const float tmpRan = pem->obj.emitedge.angle + RAND_VAR(src->objtag.emitedgeVar.angle);
	const float tmpr = pem->obj.emitedge.r + RAND_VAR(src->objtag.emitedgeVar.r);
	// 随机发射位置
	const pos_t emitPos = {pem->obj.ele.pos.x + RAND_VAR(src->emitPosVar.x),
	                       pem->obj.ele.pos.y + RAND_VAR(src->emitPosVar.y)};
	float radian = 0;//弧度缓冲
	float matht = 0; // 三角函数缓冲
	int32_t i = 0;
	//首先求出来发射坐标，如果有出屏即消除，又不在屏幕内，那么不发射
	float tmpVDir;
	pos_t tmpPos;
	while (i < nmuzzle) {
		tmpVDir = (1==nmuzzle) ? 0 : (halfC - i * C + sangle) + amend;
		++i;
		radian = CSB_DEG2RAD(-(tmpVDir + tmpRan));
		matht = CSB_sin(radian);
		tmpPos.y = -(tmpr * matht) + emitPos.y;
		matht = CSB_cos(radian);
		tmpPos.x = (tmpr * matht) + emitPos.x;
		if (CSB_FLAG_TEST(pem->bueffect, BU_EFF_OutSc) && !IN_COORD_WORLD(tmpPos)) {
			continue;
		}
		CS_BUF_RENT(emitterbu_t, ret);
		CSB_NO_VRET(ret);
		ret->b.udata = NULL;
		ret->b.attr.v.dir = CSB_fmod((tmpVDir + pem->buattr.v.dir), 360.0f);
		ret->b.ele.pos = tmpPos;
		ret->b.ele.flag = 0;
		//发射范围, 和弧度确定
		ret->b.attr.v.v = tv;
		ret->b.attr.vRate = pem->buattr.vRate;
		ret->b.attr.va = va;
		ret->b.attr.ID = pem->buattr.ID;
		ret->b.attr.life = 0;
		ret->b.attr.lifetime = pem->buattr.lifetime;
		ret->b.ele.scale = pem->buScale;
		//NOTE:受到加速度的控制
		ret->b.ele.rotate = ret->b.attr.v.dir;
		ret->color = pem->bucolor;
		ret->effect = pem->bueffect;
		ret->aclist = ac_buf_copy(src->bullet.aclist);
		// add to bulist
		list_insert(&pcsn->bulist, (void*)ret, 0, 0);
		// call on buborn
		if (pcsn->cbs.on_buborn) {
			pcsn->cbs.on_buborn((bullet_t*)ret, pcsn->cbs.udata);
		}
	}
}


void emitter_update(csnode_t* pcsn, bool updateObj, bool updateBullet)
{
	emitter_t* em = (emitter_t*)pcsn->pobj;
	// 元素事件处理
	if (1 == pcsn->nframe && em->obj.life > 1) {
		emitter_2origin((emitterdata_t*)pcsn->pobjdata, em, true);
	}
	if (updateObj) {
		ac_foreach(em->aclist, emitter_ac_for, pcsn->nframe, pcsn);
		// 遍历事件结果队列加成
		action_eff_list_for(&em->obj.ac_eff_list, emitter_aceff_for, (void*)pcsn);
		// NOTE:自机的处理
		if (NO_BODY_SELF(em->obj.ele.pos) && CSB_FLAG_TEST(em->obj.ele.flag, R_AM) && pcsn->cbs.on_am) {
			em->obj.rotateOffset = CSB_rotate_p2p(&em->obj.ele.pos, &pcsn->cbs.autoPos);
		}
		// 调整坐标，
		struct xyvlsm_t vlsmt = { 1,em->obj.ele.rotate, em->obj.v, em->obj.va, {1.0f, 1.0f}};
		pos_t offset;
		xy_vlsm(&vlsmt,&offset);
		em->obj.v = vlsmt.v;
		em->obj.ele.pos.x += offset.x;
		em->obj.ele.pos.y -= offset.y;
		if (pcsn->cbs.on_objupdate) {
			pcsn->cbs.on_objupdate(pcsn->pobj, pcsn->cbs.udata);
		}
	}
	if (updateBullet) {
		list_foreach(&pcsn->bulist, emitter_bu_update, pcsn);
	}
}


CSB_DLL void emitterbu_buf_return(emitterbu_t* pbu)
{
	CS_BUF_RETURN(emitterbu_t, pbu);
	ac_free(pbu->aclist);
	action_eff_list_clean(&pbu->b.ac_eff_list);
}


CSB_DLL void emitter_set_rotate(emitter_t* pem, const float d)
{
	pem->obj.ele.rotate = CSB_fmod((pem->obj.rotateOffset + d) , 360.0f);
	pem->buattr.v.dir = pem->obj.ele.rotate;
}

#ifdef __cplusplus
} // end of extern C
#endif
